<template>
  <div class="pc-video-cropper">
    <!-- 顶部工具栏 -->
    <div class="top-toolbar">
      <div class="toolbar-left">
        <button class="toolbar-btn primary" @click="handleImport">
          <span class="icon">📁</span>
          导入视频
        </button>
      </div>

      <div class="toolbar-center">
        <h1 class="app-title">视频裁剪demo</h1>
      </div>
    </div>

    <div class="main-content">
      <!-- 左侧预览面板 -->
      <div class="preview-panel">
        <h3 class="preview-header">视频预览</h3>
        <div class="video-container">
          <div class="video-inner">
            <video
                ref="videoPlayer"
                class="video-element"
                :src="videoSrc"
                @loadedmetadata="onVideoLoaded"
                @timeupdate="onTimeUpdate"
                @ended="onVideoEnded"
            ></video>
            <!-- 播放进度叠加层 -->
            <div
                class="playback-progress"
                :style="{ width: playbackPosition + '%' }"
            ></div>
          </div>
        </div>

        <!-- 播放控制 -->
        <div class="playback-controls">
          <span @click="stepBackward" class="control-btn" title="5秒">后退</span>
          <button @click="togglePlayPause" class="control-btn">
            <span class="icon">{{ isPlaying ? '⏸️' : '▶️' }}</span>
          </button>
          <span @click="stepForward" class="control-btn" title="前进5秒">前进</span>

          <div class="time-display">
            <span class="current-time">{{ formatTime(currentTime) }}</span>
            <span class="time-separator">/</span>
            <span class="total-time">{{ formatTime(videoDuration) }}</span>
          </div>

          <select class="playback-rate" v-model="playbackRate" @change="onPlaybackRateChange">
            <option value="0.25">0.25x</option>
            <option value="0.5">0.5x</option>
            <option value="0.75">0.75x</option>
            <option value="1">1x</option>
            <option value="1.25">1.25x</option>
            <option value="1.5">1.5x</option>
            <option value="2">2x</option>
          </select>

          <button @click="playCropRange" class="control-btn" title="播放选中范围">播放选中范围</button>
        </div>
      </div>

      <!-- 右侧控制面板 -->
      <div class="control-panel">
        <!-- 时间轴裁剪 -->
        <div class="panel-section">
          <h3 class="section-title">时间轴裁剪</h3>
          <!-- 专业时间轴 -->
          <div class="professional-timeline">
            <!-- 时间刻度 -->
            <div class="timeline-ruler">
              <div
                  v-for="(tick, index) in professionalTimeTicks"
                  :key="index"
                  class="ruler-tick"
                  :class="{ major: tick.isMajor, 'frame-tick': tick.isFrame }"
                  :style="{ left: tick.position + '%' }"
                  @click="seekToTime(tick.time)"
              >
                <div class="tick-line" :class="{ 'major-line': tick.isMajor }"></div>
                <div v-if="tick.showLabel" class="tick-label">{{ tick.label }}</div>
              </div>
            </div>

            <!-- 时间轴轨道 -->
            <div class="timeline-track" ref="timelineTrack">
              <!-- 播放进度 -->
              <div
                  class="timeline-progress"
                  :style="{ width: playbackPosition + '%' }"
              ></div>

              <!-- 裁剪范围 -->
              <div
                  class="crop-range"
                  :style="{
                  left: cropStartPercent + '%',
                  width: cropWidthPercent + '%'
                }"
                  @mousedown="startCropDrag"
              >
                <div
                    class="range-handle start-handle"
                    @mousedown="startHandleDrag('start', $event)"
                >
                  <div class="handle-grip"></div>
                </div>
                <div
                    class="range-handle end-handle"
                    @mousedown="startHandleDrag('end', $event)"
                >
                  <div class="handle-grip"></div>
                </div>
                <div class="range-info">
                  <span class="range-duration">{{ formatTime((cropEnd - cropStart) / 100) }}</span>
                </div>
              </div>
            </div>

            <!-- 当前时间指示器 -->
            <div
                class="current-time-marker"
                :style="{ left: playbackPosition + '%' }"
            >
              <div class="marker-line"></div>
              <div class="marker-time">{{ formatTime(currentTime) }}</div>
            </div>
          </div>

          <!-- 精确时间控制 -->
          <div class="precise-time-controls">
            <div class="time-input-group">
              <label>开始时间:</label>
              <div class="input-with-controls">
                <input
                    type="text"
                    v-model="startTimeInput"
                    @blur="updateStartTime"
                    @keyup.enter="updateStartTime"
                    class="time-input"
                >
                <div class="time-controls">
                  <button @click="fineTuneStart(-1)" class="micro-btn" title="减少1秒">-1s</button>
                  <button @click="fineTuneStart(-0.1)" class="micro-btn" title="减少0.1秒">-0.1s</button>
                  <button @click="seekToCropStart" class="seek-btn" title="定位">📍</button>
                  <button @click="fineTuneStart(0.1)" class="micro-btn" title="增加0.1秒">+0.1s</button>
                  <button @click="fineTuneStart(1)" class="micro-btn" title="增加1秒">+1s</button>
                </div>
              </div>
            </div>

            <div class="time-input-group">
              <label>结束时间:</label>
              <div class="input-with-controls">
                <input
                    type="text"
                    v-model="endTimeInput"
                    @blur="updateEndTime"
                    @keyup.enter="updateEndTime"
                    class="time-input"
                >
                <div class="time-controls">
                  <button @click="fineTuneEnd(-1)" class="micro-btn" title="减少1秒">-1s</button>
                  <button @click="fineTuneEnd(-0.1)" class="micro-btn" title="减少0.1秒">-0.1s</button>
                  <button @click="seekToCropEnd" class="seek-btn" title="定位">📍</button>
                  <button @click="fineTuneEnd(0.1)" class="micro-btn" title="增加0.1秒">+0.1s</button>
                  <button @click="fineTuneEnd(1)" class="micro-btn" title="增加1秒">+1s</button>
                </div>
              </div>
            </div>
          </div>

          <!-- 快速操作 -->
          <div class="quick-actions">
            <button @click="setCropToStart" class="quick-btn">
              <span class="icon">⏮️</span>
              视频开头
            </button>
            <button @click="setCropToEnd" class="quick-btn">
              <span class="icon">⏭️</span>
              视频结尾
            </button>
            <button @click="selectAll" class="quick-btn">
              <span class="icon">📏</span>
              选择全部
            </button>
            <button @click="clearCrop" class="quick-btn">
              <span class="icon">❌</span>
              清除选择
            </button>
          </div>
        </div>

        <!-- 输出设置 -->
        <div class="panel-section">
          <h3 class="section-title">
            <span class="icon">⚡</span>
            输出设置
          </h3>

          <div class="output-settings">
            <div class="setting-row">
              <div class="setting-item">
                <label>输出格式:</label>
                <select v-model="outputFormat" class="setting-select">
                  <option value="mp4">MP4 (H.264)</option>
                  <option value="mov">MOV (ProRes)</option>
                  <option value="avi">AVI</option>
                  <option value="webm">WebM</option>
                </select>
              </div>

              <div class="setting-item">
                <label>视频编码:</label>
                <select v-model="videoCodec" class="setting-select">
                  <option value="h264">H.264</option>
                  <option value="h265">H.265 (HEVC)</option>
                  <option value="prores">ProRes</option>
                </select>
              </div>
            </div>

            <div class="setting-row">
              <div class="setting-item">
                <label>分辨率:</label>
                <select v-model="outputResolution" class="setting-select">
                  <option value="original">原始分辨率</option>
                  <option value="4k">4K (3840x2160)</option>
                  <option value="1080p">1080p (1920x1080)</option>
                  <option value="720p">720p (1280x720)</option>
                  <option value="480p">480p (854x480)</option>
                </select>
              </div>

              <div class="setting-item">
                <label>帧率:</label>
                <select v-model="outputFrameRate" class="setting-select">
                  <option value="original">原始帧率</option>
                  <option value="60">60 fps</option>
                  <option value="30">30 fps</option>
                  <option value="25">25 fps</option>
                  <option value="24">24 fps</option>
                </select>
              </div>
            </div>

            <div class="setting-row">
              <div class="setting-item">
                <label>视频质量:</label>
                <div class="quality-slider">
                  <input
                      type="range"
                      min="1"
                      max="10"
                      v-model="outputQuality"
                      class="quality-range"
                  >
                  <span class="quality-value">{{ outputQuality }}/10</span>
                </div>
              </div>

              <div class="setting-item">
                <label>音频质量:</label>
                <select v-model="audioQuality" class="setting-select">
                  <option value="original">原始质量</option>
                  <option value="320k">320 kbps</option>
                  <option value="256k">256 kbps</option>
                  <option value="192k">192 kbps</option>
                  <option value="128k">128 kbps</option>
                </select>
              </div>
            </div>
          </div>
        </div>

        <!-- 处理选项 -->
        <div class="panel-section">
          <h3 class="section-title">
            <span class="icon">🔧</span>
            处理选项
          </h3>

          <div class="processing-options">
            <div class="option-group">
              <label class="checkbox-label">
                <input type="checkbox" v-model="removeAudio" class="checkbox">
                <span class="checkmark"></span>
                移除音频
              </label>

              <label class="checkbox-label">
                <input type="checkbox" v-model="preserveMetadata" class="checkbox">
                <span class="checkmark"></span>
                保留元数据
              </label>

              <label class="checkbox-label">
                <input type="checkbox" v-model="hardwareAcceleration" class="checkbox">
                <span class="checkmark"></span>
                硬件加速
              </label>
            </div>

            <div class="option-group">
              <label class="checkbox-label">
                <input type="checkbox" v-model="multiThreading" class="checkbox">
                <span class="checkmark"></span>
                多线程处理
              </label>

              <label class="checkbox-label">
                <input type="checkbox" v-model="previewMode" class="checkbox">
                <span class="checkmark"></span>
                预览模式（快速处理）
              </label>
            </div>
          </div>
        </div>

        <!-- 操作按钮 -->
        <div class="action-buttons">
          <button @click="previewOutput" class="btn-secondary" :disabled="!videoSrc">
            <span class="icon">👁️</span>
            预览输出
          </button>
          <button @click="resetAll" class="btn-secondary">
            <span class="icon">🔄</span>
            重置所有
          </button>
          <button @click="downloadCroppedVideo" class="btn-primary" :disabled="!videoSrc || isProcessing">
            <span class="icon">🎬</span>
            {{ isProcessing ? '处理中...' : '开始处理' }}
          </button>
        </div>
      </div>
    </div>

    <!-- 处理进度 -->
    <div v-if="isProcessing" class="processing-overlay">
      <div class="processing-modal">
        <h3>视频处理中</h3>
        <div class="progress-section">
          <div class="progress-bar">
            <div
                class="progress-fill"
                :style="{ width: progressPercent + '%' }"
            ></div>
          </div>
          <div class="progress-info">
            <span class="progress-percent">{{ progressPercent }}%</span>
            <span class="progress-message">{{ progressMessage }}</span>
          </div>
        </div>
        <div class="processing-details">
          <div class="detail-item">
            <span class="detail-label">已用时间:</span>
            <span class="detail-value">{{ processingTime }}</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">预估剩余:</span>
            <span class="detail-value">{{ estimatedTimeRemaining }}</span>
          </div>
        </div>
        <button @click="cancelProcessing" class="cancel-btn">
          取消处理
        </button>
      </div>
    </div>

    <!-- 文件输入 -->
    <input
        type="file"
        ref="fileInput"
        accept="video/*"
        style="display: none"
        @change="onFileSelected"
    >
  </div>
</template>

<script setup lang="ts">
import {computed, onUnmounted, ref, watch} from 'vue'
import {FFmpeg} from '@ffmpeg/ffmpeg'
import {fetchFile, toBlobURL} from '@ffmpeg/util'

// FFmpeg 实例
const ffmpeg = new FFmpeg()
// 响应式数据
const videoSrc = ref<string>('')
const videoDuration = ref<number>(0)
const currentTime = ref<number>(0)
const cropStart = ref<number>(0)
const cropEnd = ref<number>(0)
const isPlaying = ref<boolean>(false)
const isProcessing = ref<boolean>(false)
const progressPercent = ref<number>(0)
const progressMessage = ref<string>('')
const zoomLevel = ref<number>(1)
const playbackRate = ref<string>('1')
const showSettings = ref<boolean>(false)

// 输出设置
const outputFormat = ref<string>('mp4')
const videoCodec = ref<string>('h264')
const outputResolution = ref<string>('original')
const outputFrameRate = ref<string>('original')
const outputQuality = ref<number>(8)
const audioQuality = ref<string>('original')

// 处理选项
const removeAudio = ref<boolean>(false)
const preserveMetadata = ref<boolean>(true)
const hardwareAcceleration = ref<boolean>(true)
const multiThreading = ref<boolean>(true)
const previewMode = ref<boolean>(false)

// 拖拽状态
const isDragging = ref<boolean>(false)
const dragType = ref<string>('')
const dragStartX = ref<number>(0)
const dragStartValue = ref<number>(0)

// 精确时间输入
const startTimeInput = ref<string>('')
const endTimeInput = ref<string>('')

// 处理时间
const processingTime = ref<string>('00:00')
const estimatedTimeRemaining = ref<string>('00:00')

// DOM 引用
const fileInput = ref<HTMLInputElement | null>(null)
const videoPlayer = ref<HTMLVideoElement | null>(null)
const timelineTrack = ref<HTMLDivElement | null>(null)

// 计算属性
const playbackPosition = computed(() => {
  if (videoDuration.value === 0) return 0
  return (currentTime.value / videoDuration.value) * 100
})

const cropStartPercent = computed(() => {
  return (cropStart.value / (videoDuration.value * 100)) * 100
})

const cropWidthPercent = computed(() => {
  return ((cropEnd.value - cropStart.value) / (videoDuration.value * 100)) * 100
})

// 专业时间刻度
const professionalTimeTicks = computed(() => {
  if (videoDuration.value === 0) return []

  const ticks = []
  const totalSeconds = videoDuration.value
  // 根据视频长度确定刻度间隔
  let interval: number
  if (totalSeconds <= 10) {
    interval = 1 // 每秒
  } else if (totalSeconds <= 30) {
    interval = 2 // 每2秒
  } else if (totalSeconds <= 120) {
    interval = 5 // 每5秒
  } else if (totalSeconds <= 300) {
    interval = 10 // 每10秒
  } else if (totalSeconds <= 600) {
    interval = 30 // 每30秒
  } else {
    interval = 60 // 每分钟
  }
  for (let i = 0; i <= totalSeconds; i += interval) {
    const time = i
    const position = (time / totalSeconds) * 100

    const isMajor = time % 60 === 0 || (totalSeconds <= 60 && time % 10 === 0)
    const isFrame = time % 1 === 0 && totalSeconds <= 10

    let showLabel = false
    let label = ''

    if (time % 60 === 0 || (totalSeconds <= 60 && time % 10 === 0)) {
      if (time < 60) {
        label = `${time}s`
      } else if (time < 3600) {
        const minutes = Math.floor(time / 60)
        label = `${minutes}m`
      } else {
        const hours = Math.floor(time / 3600)
        const minutes = Math.floor((time % 3600) / 60)
        label = `${hours}h${minutes}m`
      }
      showLabel = true
    }

    ticks.push({
      time,
      position,
      label,
      isMajor,
      isFrame,
      showLabel
    })
  }

  return ticks
})

// 时间格式化
const formatTime = (seconds: number): string => {
  const totalSeconds = Math.floor(seconds)
  const hours = Math.floor(totalSeconds / 3600)
  const minutes = Math.floor((totalSeconds % 3600) / 60)
  const secs = totalSeconds % 60

  if (hours > 0) {
    return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
  }
  return `${minutes}:${secs.toString().padStart(2, '0')}`
}

// 更新时间输入框
const updateTimeStringInputs = () => {
  startTimeInput.value = formatTime(cropStart.value / 100)
  endTimeInput.value = formatTime(cropEnd.value / 100)
}

// 视频处理
const handleImport = () => {
  fileInput.value?.click()
}

const onFileSelected = (event: Event) => {
  const target = event.target as HTMLInputElement
  const files = target.files

  if (files && files.length > 0) {
    const file = files[0]
    if (file.type.startsWith('video/')) {
      videoSrc.value = URL.createObjectURL(file)
      console.log(URL.createObjectURL(file));
    }
  }
}

const onVideoLoaded = () => {
  if (videoPlayer.value) {
    videoDuration.value = videoPlayer.value.duration
    cropStart.value = 0
    cropEnd.value = videoDuration.value * 100
    updateTimeStringInputs()
  }
}

const onTimeUpdate = () => {
  if (videoPlayer.value) {
    currentTime.value = videoPlayer.value.currentTime

    if (currentTime.value >= cropEnd.value / 100 && isPlaying.value) {
      videoPlayer.value.pause()
      isPlaying.value = false
    }
  }
}

const onVideoEnded = () => {
  isPlaying.value = false
}

// 播放控制
const togglePlayPause = () => {
  if (videoPlayer.value) {
    if (videoPlayer.value.paused) {
      videoPlayer.value.play()
      isPlaying.value = true
    } else {
      videoPlayer.value.pause()
      isPlaying.value = false
    }
  }
}

const playCropRange = () => {
  if (videoPlayer.value) {
    videoPlayer.value.currentTime = cropStart.value / 100
    videoPlayer.value.play()
    isPlaying.value = true
  }
}

const stepBackward = () => {
  if (videoPlayer.value) {
    videoPlayer.value.currentTime = Math.max(0, videoPlayer.value.currentTime - 5)
  }
}

const stepForward = () => {
  if (videoPlayer.value) {
    videoPlayer.value.currentTime = Math.min(videoDuration.value, videoPlayer.value.currentTime + 5)
  }
}

const onPlaybackRateChange = () => {
  if (videoPlayer.value) {
    videoPlayer.value.playbackRate = parseFloat(playbackRate.value)
  }
}
// 时间轴拖拽
const startHandleDrag = (type: string, event: MouseEvent) => {
  event.preventDefault()
  event.stopPropagation()

  isDragging.value = true
  dragType.value = type
  dragStartX.value = event.clientX
  dragStartValue.value = type === 'start' ? cropStart.value : cropEnd.value

  document.addEventListener('mousemove', handleDrag)
  document.addEventListener('mouseup', stopDrag)
}

const startCropDrag = (event: MouseEvent) => {
  event.preventDefault()

  isDragging.value = true
  dragType.value = 'range'
  dragStartX.value = event.clientX
  dragStartValue.value = cropStart.value

  document.addEventListener('mousemove', handleDrag)
  document.addEventListener('mouseup', stopDrag)
}

const handleDrag = (event: MouseEvent) => {
  if (!isDragging.value || !timelineTrack.value) return

  const trackRect = timelineTrack.value.getBoundingClientRect()
  const deltaX = event.clientX - dragStartX.value
  const deltaPercentage = (deltaX / trackRect.width) * 100
  const deltaTime = (deltaPercentage / 100) * videoDuration.value * 100

  if (dragType.value === 'start') {
    cropStart.value = Math.max(0, Math.min(dragStartValue.value + deltaTime, cropEnd.value - 100))
  } else if (dragType.value === 'end') {
    cropEnd.value = Math.min(videoDuration.value * 100, Math.max(dragStartValue.value + deltaTime, cropStart.value + 100))
  } else if (dragType.value === 'range') {
    const newStart = Math.max(0, Math.min(dragStartValue.value + deltaTime, videoDuration.value * 100 - (cropEnd.value - cropStart.value)))
    const rangeWidth = cropEnd.value - cropStart.value
    cropStart.value = newStart
    cropEnd.value = newStart + rangeWidth
  }

  updateTimeStringInputs()
}

const stopDrag = () => {
  isDragging.value = false
  dragType.value = ''
  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
}

// 时间控制
const seekToTime = (time: number) => {
  if (videoPlayer.value) {
    videoPlayer.value.currentTime = time
  }
}

const seekToCropStart = () => {
  if (videoPlayer.value) {
    videoPlayer.value.currentTime = cropStart.value / 100
  }
}

const seekToCropEnd = () => {
  if (videoPlayer.value) {
    videoPlayer.value.currentTime = cropEnd.value / 100
  }
}

const fineTuneStart = (seconds: number) => {
  const newStart = cropStart.value + (seconds * 100)
  if (newStart >= 0 && newStart < cropEnd.value) {
    cropStart.value = newStart
    updateTimeStringInputs()
  }
}

const fineTuneEnd = (seconds: number) => {
  const newEnd = cropEnd.value + (seconds * 100)
  if (newEnd > cropStart.value && newEnd <= videoDuration.value * 100) {
    cropEnd.value = newEnd
    updateTimeStringInputs()
  }
}

// 快速操作
const setCropToStart = () => {
  cropStart.value = 0
  updateTimeStringInputs()
}

const setCropToEnd = () => {
  cropEnd.value = videoDuration.value * 100
  updateTimeStringInputs()
}

const selectAll = () => {
  cropStart.value = 0
  cropEnd.value = videoDuration.value * 100
  updateTimeStringInputs()
}

const clearCrop = () => {
  cropStart.value = 0
  cropEnd.value = 0
  updateTimeStringInputs()
}

// 精确时间输入
const updateStartTime = () => {
  const time = parseTimeString(startTimeInput.value)
  if (time !== null && time >= 0 && time <= cropEnd.value / 100) {
    cropStart.value = time * 100
  } else {
    updateTimeStringInputs()
  }
}

const updateEndTime = () => {
  const time = parseTimeString(endTimeInput.value)
  if (time !== null && time >= cropStart.value / 100 && time <= videoDuration.value) {
    cropEnd.value = time * 100
  } else {
    updateTimeStringInputs()
  }
}

const parseTimeString = (timeStr: string): number | null => {
  const parts = timeStr.split(':')
  if (parts.length === 2) {
    return (parseInt(parts[0]) || 0) * 60 + (parseInt(parts[1]) || 0)
  } else if (parts.length === 3) {
    return (parseInt(parts[0]) || 0) * 3600 + (parseInt(parts[1]) || 0) * 60 + (parseInt(parts[2]) || 0)
  }
  return null
}

// 处理功能
const previewOutput = () => {
  console.log('预览输出', {
    start: cropStart.value / 100,
    end: cropEnd.value / 100,
    format: outputFormat.value,
    resolution: outputResolution.value
  })
  alert('预览功能开发中...')
}

const resetAll = () => {
  cropStart.value = 0
  cropEnd.value = videoDuration.value * 100
  zoomLevel.value = 1
  playbackRate.value = '1'
  updateTimeStringInputs()
}
const cancelProcessing = () => {
  isProcessing.value = false
  progressPercent.value = 0
  progressMessage.value = '处理已取消'
}

// 下载裁剪视频
// https://juejin.cn/post/7472400354993455119?searchId=20251014085312C3597DF7E6BA962F73CA
const downloadCroppedVideo = async () => {
  if (!videoPlayer.value) return
  try {
    ffmpeg.on('log', ({ message }) => {
      console.log(message);
    });
    ffmpeg.on('progress', ({ progress }) => {
      console.log(progress);
    });
    await ffmpeg.load({
      coreURL: await toBlobURL('/ffmpeg/ffmpeg-core.js', 'text/javascript'),
      wasmURL: await toBlobURL('/ffmpeg/ffmpeg-core.wasm', 'application/wasm'),
      workerURL: await toBlobURL('/ffmpeg/ffmpeg-core.worker.js', 'text/javascript')
    })
    await ffmpeg.writeFile('test.mp4', await fetchFile(videoSrc.value))
    await ffmpeg.writeFile('arial.ttf', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/arial.ttf'));
    // 执行裁剪命令
    const startTimeSeconds = cropStart.value / 100
    const endTimeSeconds = cropEnd.value / 100
    const command1 = [
      '-i', 'test.mp4',
      '-ss', startTimeSeconds.toString(),
      '-t', endTimeSeconds.toString(),
      '-c', 'copy',
      'output.mp4'
    ]
    // 添加文本
    const command2 = [
      '-i', 'test.mp4',
      '-vf',
      'drawtext=fontfile=/arial.ttf:text=\'dsdasda\':x=10:y=10:fontsize=24:fontcolor=white',
      'output.mp4',
    ]
    await ffmpeg.exec(command1)
    // 获取输出文件
    const data = await ffmpeg.readFile('output.mp4')
    const blob = new Blob([data.buffer], { type: 'video/mp4' })
    const url = URL.createObjectURL(blob)
    // 创建下载链接
    const a = document.createElement('a')
    a.href = url
    a.download = `cropped-video-${Date.now()}.mp4`
    a.click()
    // 清理URL对象
    URL.revokeObjectURL(url)
    // 更新进度
    progressPercent.value = 100
    progressMessage.value = '视频已成功下载！'
    setTimeout(() => {
      isProcessing.value = false
    }, 1000)
  } catch (error) {
    console.error('下载失败:', error)
    isProcessing.value = false
  }
}

// 监听时间变化
watch([cropStart, cropEnd], () => {
  updateTimeStringInputs()
})

// 组件卸载时清理
onUnmounted(() => {
  if (videoSrc.value) {
    URL.revokeObjectURL(videoSrc.value)
  }
})
</script>

<style scoped>
.pc-video-cropper {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f8f9fa;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* 顶部工具栏 */
.top-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 24px;
  background: white;
  border-bottom: 1px solid #e1e5e9;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.toolbar-left {
  display: flex;
  gap: 8px;
}

.toolbar-center {
  flex: 1;
  text-align: center;
}

.app-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #333;
}

.toolbar-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: white;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
}

.toolbar-btn.primary {
  background: #007bff;
  color: white;
  border-color: #007bff;
}

.toolbar-btn:hover {
  background: #f6f8fa;
  border-color: #afb8c1;
}

.toolbar-btn.primary:hover {
  background: #0056b3;
  border-color: #0056b3;
}

.icon {
  font-size: 14px;
}

/* 主内容区域 */
.main-content {
  display: flex;
  flex: 1;
  gap: 24px;
  padding: 24px;
  overflow: hidden;
}

.preview-panel {
  flex: 1;
  background: white;
  border-radius: 8px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.preview-header h3 {
  margin: 0;
  color: #333;
  font-size: 16px;
  font-weight: 600;
}

/* 视频容器 */
.video-container {
  flex: 1;
  background: #000;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  transform-origin: center center;
  transition: transform 0.2s;
}
.video-inner {
  position: relative;
}
.video-element {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.playback-progress {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: rgba(0, 123, 255, 0.3);
  pointer-events: none;
  transition: width 0.1s linear;
}

/* 播放控制 */
.playback-controls {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 16px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
}

.control-btn {
  padding: 6px 12px;
  background: white;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  user-select: none;
}

.time-display {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.current-time {
  color: #007bff;
  font-weight: 600;
}

.time-separator {
  color: #666;
}

.total-time {
  color: #333;
}

.playback-rate {
  padding: 6px 8px;
  border: 1px solid #d0d7de;
  border-radius: 4px;
  background: white;
  font-size: 12px;
  outline: none;
}

/* 控制面板 */
.control-panel {
  width: 400px;
  background: white;
  border-radius: 8px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  overflow-y: auto;
}

.panel-section {
  border-bottom: 1px solid #e1e5e9;
  padding-bottom: 20px;
}

.panel-section:last-child {
  border-bottom: none;
}

.section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 16px 0;
  font-size: 16px;
  color: #333;
  font-weight: 600;
}

/* 专业时间轴 */
.professional-timeline {
  position: relative;
  margin-bottom: 20px;
}

.timeline-ruler {
  position: relative;
  height: 20px;
  margin-bottom: 10px;
}

.ruler-tick {
  position: absolute;
  bottom: 0;
  transform: translateX(-50%);
  cursor: pointer;
}

.tick-line {
  width: 1px;
  background: #ccc;
  margin: 0 auto;
  transition: all 0.2s;
}

.tick-line.major-line {
  background: #666;
  width: 2px;
  height: 12px;
}

.ruler-tick:not(.major) .tick-line {
  height: 8px;
}

.ruler-tick.frame-tick .tick-line {
  height: 4px;
  background: #999;
}

.tick-label {
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 11px;
  color: #666;
  white-space: nowrap;
  font-family: 'Monaco', 'Menlo', monospace;
}

.timeline-track {
  position: relative;
  height: 40px;
  background: #e1e5e9;
  border-radius: 6px;
  cursor: pointer;
}

.timeline-progress {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: rgba(0, 123, 255, 0.1);
  pointer-events: none;
  border-radius: 6px;
}

.crop-range {
  position: absolute;
  top: 0;
  height: 100%;
  background: rgba(40, 167, 69, 0.2);
  border: 1px solid #28a745;
  border-radius: 4px;
  cursor: move;
  user-select: none;
}

.range-handle {
  position: absolute;
  top: 0;
  width: 4px;
  height: 100%;
  cursor: col-resize;
  display: flex;
  align-items: center;
  justify-content: center;
}

.start-handle {
  left: 0;
}

.end-handle {
  right: 0px;
}

.handle-grip {
  width: 4px;
  height: 24px;
  background: #28a745;
}

.range-info {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.range-duration {
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
  font-family: 'Monaco', 'Menlo', monospace;
}

.current-time-marker {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 10;
}

.marker-line {
  width: 2px;
  height: 28px;
  background: #dc3545;
  margin: 0 auto;
}

.marker-time {
  position: absolute;
  top: -25px;
  left: 50%;
  transform: translateX(-50%);
  background: #dc3545;
  color: white;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 12px;
  white-space: nowrap;
}

/* 精确时间控制 */
.precise-time-controls {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.time-input-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.time-input-group label {
  font-size: 12px;
  color: #666;
  font-weight: 500;
}

.input-with-controls {
  display: flex;
  gap: 8px;
}

.time-input {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #d0d7de;
  border-radius: 4px;
  font-family: 'Monaco', 'Menlo', monospace;
}

.time-controls {
  display: flex;
  gap: 4px;
}

.micro-btn, .seek-btn {
  padding: 6px 8px;
  background: #6c757d;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 10px;
  white-space: nowrap;
}

.micro-btn:hover, .seek-btn:hover {
  background: #5a6268;
}

/* 快速操作 */
.quick-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.quick-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: #f8f9fa;
  border: 1px solid #d0d7de;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  transition: all 0.2s;
}

.quick-btn:hover {
  background: #e9ecef;
}

/* 输出设置 */
.output-settings {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.setting-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.setting-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.setting-item label {
  font-size: 12px;
  color: #666;
  font-weight: 500;
}

.setting-select {
  padding: 6px 8px;
  border: 1px solid #d0d7de;
  border-radius: 4px;
  background: white;
  font-size: 12px;
}

.quality-slider {
  display: flex;
  align-items: center;
  gap: 8px;
}

.quality-range {
  flex: 1;
}

.quality-value {
  font-size: 11px;
  color: #666;
  min-width: 30px;
  text-align: center;
  font-family: 'Monaco', 'Menlo', monospace;
}

/* 处理选项 */
.processing-options {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.option-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 14px;
  color: #333;
}

.checkbox {
  display: none;
}

.checkmark {
  width: 16px;
  height: 16px;
  border: 2px solid #d0d7de;
  border-radius: 3px;
  position: relative;
  transition: all 0.2s;
}

.checkbox:checked + .checkmark {
  background: #007bff;
  border-color: #007bff;
}

.checkbox:checked + .checkmark::after {
  content: '✓';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: white;
  font-size: 12px;
  font-weight: bold;
}

/* 操作按钮 */
.action-buttons {
  display: flex;
  gap: 12px;
  margin-top: auto;
}

.btn-primary, .btn-secondary {
  flex: 1;
  padding: 12px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.btn-primary {
  background: #007bff;
  color: white;
}

.btn-primary:hover:not(:disabled) {
  background: #0056b3;
}

.btn-primary:disabled {
  background: #6c757d;
  cursor: not-allowed;
}

.btn-secondary {
  background: #6c757d;
  color: white;
}

.btn-secondary:hover {
  background: #5a6268;
}

/* 处理进度 */
.processing-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.processing-modal {
  background: white;
  border-radius: 8px;
  padding: 24px;
  width: 400px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.processing-modal h3 {
  margin: 0 0 16px 0;
  text-align: center;
  color: #333;
}

.progress-section {
  margin-bottom: 16px;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: #f0f0f0;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #007bff, #28a745);
  transition: width 0.3s ease;
}

.progress-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.progress-percent {
  font-weight: 600;
  color: #007bff;
  font-family: 'Monaco', 'Menlo', monospace;
}

.progress-message {
  font-size: 12px;
  color: #666;
}

.processing-details {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 16px;
  padding: 12px;
  background: #f8f9fa;
  border-radius: 4px;
}

.detail-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.detail-label {
  font-size: 11px;
  color: #666;
}

.detail-value {
  font-size: 12px;
  color: #333;
  font-weight: 600;
  font-family: 'Monaco', 'Menlo', monospace;
}

.cancel-btn {
  width: 100%;
  padding: 10px 16px;
  background: #dc3545;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

.cancel-btn:hover {
  background: #c82333;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .main-content {
    flex-direction: column;
  }

  .control-panel {
    width: 100%;
  }
}

@media (max-width: 768px) {
  .top-toolbar {
    padding: 8px 16px;
  }

  .main-content {
    padding: 16px;
    gap: 16px;
  }

  .setting-row {
    grid-template-columns: 1fr;
  }

  .quick-actions {
    grid-template-columns: 1fr;
  }

  .action-buttons {
    flex-direction: column;
  }
}
</style>
